package com.bolt.admin.web.controller;

import com.bolt.admin.exception.BizExceptionEnum;
import com.bolt.admin.module.sys.dto.LoginDTO;
import com.bolt.admin.module.sys.entity.LoginLogEntity;
import com.bolt.admin.module.sys.entity.UserEntity;
import com.bolt.admin.module.sys.service.OnlineUserService;
import com.bolt.admin.module.sys.service.UserService;
import com.bolt.admin.properties.LoginProperties;
import com.bolt.admin.security.shiro.PasswordUtil;
import com.bolt.admin.security.shiro.jwt.TokenProvider;
import com.bolt.admin.security.shiro.jwt.UserInfo;
import com.bolt.common.utils.StrUtil;
import com.bolt.common.web.RequestUtil;
import com.bolt.convention.data.ResultMessage;
import com.bolt.convention.data.Results;
import com.bolt.convention.data.Record;
import com.bolt.support.cache.redis.RedisManager;
import com.wf.captcha.base.Captcha;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@RequiredArgsConstructor
@Api(tags = "登录有关")
@RequestMapping("/api")
public class LoginController {

    private final LoginProperties loginProperties;

    private final RedisManager redisManager;

    private final UserService userService;

    private final TokenProvider tokenProvider;

    private final OnlineUserService onlineUserService;


    @PostMapping("/auth/login")
    public ResultMessage <UserInfo> login(@Validated @RequestBody LoginDTO loginDTO, HttpServletRequest servletRequest) {
        if (loginProperties.getCaptchaCode().isEnabled()) {
            if (StrUtil.isBlank(loginDTO.getGraphId()) || StrUtil.isBlank(loginDTO.getCaptcha())) {
                return Results.failure(BizExceptionEnum.AUTH_CAPTCHA_EXPIRED_ERROR);
            }
            // 查询验证码
            String code = redisManager.get(loginDTO.getGraphId());
            // 清除验证码
            redisManager.del(loginDTO.getGraphId());
            if (StrUtil.isBlank(code)) {
                return Results.failure(BizExceptionEnum.AUTH_CAPTCHA_EXPIRED_ERROR);
            }
            if (StrUtil.isBlank(loginDTO.getCaptcha()) || !loginDTO.getCaptcha().equalsIgnoreCase(code)) {
                return Results.failure(BizExceptionEnum.AUTH_CAPTCHA_VERIFY_ERROR);
            }
        }

        Optional <UserEntity> userEntity = userService.findByUserName(loginDTO.getUsername());
        if (userEntity.isPresent()) {
            UserEntity user = userEntity.get();
            String password = PasswordUtil.entryptPassword(loginDTO.getPassword(), user.getAuthSalt());
            if (password.equals(user.getPassword())) {
                return Results.failure(BizExceptionEnum.USER_NOT_EXISTED);
            }
            //写入登入记录信息
            LoginLogEntity userLoginLog = new LoginLogEntity();
            userLoginLog.setUser(user);
            userLoginLog.setLogonTime(LocalDateTime.now());
            userLoginLog.setRemoteAddr(servletRequest.getRemoteAddr());
            userLoginLog.setRemoteHost(servletRequest.getRemoteHost());
            userLoginLog.setRemotePort(servletRequest.getRemotePort());
            userLoginLog.setUserAgent(servletRequest.getHeader("User-Agent"));
            userLoginLog.setXforwardFor(RequestUtil.getRemoteIpAddress(servletRequest));
            userService.saveLoginLog(userLoginLog);

            //取出用户信息
            UserInfo userInfo = userService.userInfo(user.getId());
            String accessToken = tokenProvider.createToken(user.getId());
            onlineUserService.save(userInfo, accessToken, loginProperties.getJwt().getExpiration(), servletRequest);

            userInfo.setAccessToken(loginProperties.getJwt().getTokenStartWith() + accessToken);

            return Results.success(userInfo);
        } else {
            return Results.failure(BizExceptionEnum.USER_NOT_EXISTED);
        }
    }


    @PostMapping("/auth/logout")
    public ResultMessage <Void> logout(HttpServletRequest request) {
        //清除缓存
        Subject subject = SecurityUtils.getSubject();
        if (subject != null) {
            SecurityUtils.getSecurityManager().logout(subject);
        }
        onlineUserService.logOut(tokenProvider.getToken(request));
        return Results.success();
    }

    @RequestMapping(value = "/captcha/graph")
    public ResultMessage <Record> captchaGraph() {
        Record resultMap = new Record();
        String uuid = UUID.randomUUID().toString();
        Captcha captcha = loginProperties.getCaptcha();
        resultMap.put("graphId", uuid);
        resultMap.put("img", captcha.toBase64());
        redisManager.cache(uuid, captcha.text(), loginProperties.getCaptchaCode().getExpiration(), TimeUnit.MINUTES);
        return Results.success(resultMap);
    }
}

 